import axios from 'axios'
import { http, api } from './http'
import Api from '../../build/config'
import { faceFileApi } from './const'
class File {
  constructor () {
    this.imgServerApi = faceFileApi
    this.ossUri = ''
    this.token = null
    this.fileTypes = {
      img: {
        message: '请上传png/jpg类型的图片',
        reg: /(png|jpg|jpeg)/i
      }
    }
    this.timestamp = 0
    this.effectiveTime = 14 * 60 * 1000
  }

  /**
     * 获取用于上传到阿里云的信息
     */
  async initToken () {
    try {
      // 过期前不重复获取token
      if (
        Date.now() - this.timestamp > this.effectiveTime ||
                this.timestamp === 0
      ) {
        await this.refreshToken()
      }
    } catch (err) {
      console.log(err)
    }
  }

  getFileUrlById (id) {
    return `${this.imgServerApi}/v1/inner/face_files/${id}`
  }

  getFileUrlByName (name) {
    return `${this.imgServerApi}/v1/open/files?file_name=${name}`
  }

  getFileUrl (info, isName) {
    const path = isName ? this.getFileUrlByName(info) : this.getFileUrlById(info)
    return axios({
      withCredentials: true,
      method: 'get',
      url: path
    }).then(res => res.data.result)
  }

  async refreshToken () {
    this.timestamp = Date.now()
    const { token } = await http.req(api.upload_token, null, null)
    this.ossUri = `//${token.bucket}.${token.region}.aliyuncs.com`
    this.token = {
      OSSAccessKeyId: token.AccessKeyId,
      Signature: token.signature,
      policy: token.policy,
      'x-oss-security-token': token.SecurityToken
    }
  }

  /**
     * 验证文件合法性
     * @param {Blob} file
     * @param {string} fileType 文件类型
     * @param {number} fileSize 文件最大大小 mb
     * @param {{}} vm 实例对象
     */
  isValidatedFile (file, fileType, fileSize, vm) {
    const errors = []
    const suffix = this.generateFileSuffix(file)
    if (!this.fileTypes[fileType].reg.test(suffix)) {
      errors.push(this.fileTypes[fileType].message)
    }
    if (file.size > fileSize * 1024 * 1024) {
      errors.push(`文件最大支持${fileSize}mb`)
    }
    if (errors.length && vm && vm.$Message) {
      for (let message of errors) {
        vm.$Message.info(message)
      }
    }
    return errors.length === 0
  }

  generateFileSuffix (file) {
    return file.name.split('.').pop()
  }

  /**
     * 根据文件类型, 生成新的文件名
     */
  generateFilename (file, onlyFlag) {
    const suffix = this.generateFileSuffix(file)
    return `saas-${
      onlyFlag === '' ? '' : onlyFlag + '-'
    }${Math.floor(Math.random() * 1000)}-${Date.now()}.${suffix}`
  }

  generateFormData (file, filename, isDefault = false, params) {
    const formData = new window.FormData()
    if (!isDefault) {
      formData.set('key', filename)
      for (let i in this.token) {
        formData.set(i, this.token[i])
      }
    } else {
      Object.keys(params).forEach(key => {
        formData.set(key, params[key])
      })
    }
    formData.set('file', file, filename)
    return formData
  }

  generateHeaders () {
    return {
      'Content-Type': 'multipart/form-data'
    }
  }

  async accessControllUpload (file) {
    const data = this.generateFormData(file, `saas-${Math.floor(Math.random() * 1000)}-${Date.now()}.jpg`, true, {})
    const headers = this.generateHeaders()

    return await axios({
      withCredentials: true,
      data,
      headers,
      url: faceFileApi + '/v1/inner/face_files',
      method: 'post'
    })
  }

  /**
     * @param { Blob } file 文件对象
     * @param { { } } vm 组件实例, 实例存在setProgress方法时调用该方法
     */
  async alipayUpload (file, vm, obj) {
    const filename = this.generateFilename(file)
    const data = this.generateFormData(file, filename, true, obj)
    const headers = this.generateHeaders()
    const baseUrl = process && process.env && process.env.NODE_ENV === 'production' ? Api.sass : '' // 线上环境api一律使用绝对地址

    return await axios({
      withCredentials: true,
      data,
      headers,
      url: baseUrl + '/v3/ali_pay/upload_photo',
      method: 'post',
      onUploadProgress: progress => {
        const { loaded, total } = progress
        if (vm && vm.setProgress) {
          vm.setProgress(Math.floor((loaded / total) * 100))
        }
      }
    })
  }

  /**
     * 上传文件, 并保存文件记录
     * @param {Blob} file 文件对象
     * @param {{}} vm 组件实例, 实例存在setProgress方法时调用该方法
     * @param {String} onlyFlag 唯一标识
     */
  async upload (file, vm, onlyFlag) {
    await this.initToken()
    const filename = this.generateFilename(file, onlyFlag)
    const data = this.generateFormData(file, filename)
    const headers = this.generateHeaders()
    if (!this.ossUri) {
      await this.refreshToken()
    }
    try {
      await axios({
        data,
        headers,
        url: this.ossUri,
        method: 'post',
        onUploadProgress: progress => {
          const { loaded, total } = progress
          if (vm && vm.setProgress) {
            vm.setProgress(Math.floor((loaded / total) * 100))
          }
        }
      })
    } catch (err) {
      console.log(err)
      this.refreshToken()
      vm && vm.$Message.error('上传失败，请重试')
      throw new Error('oss上传失败')
    }
    return http.req(api.upload_create, null, { name: filename })
  }
}

export default new File()
